package mark.tom.narcissus;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

import java.util.HashMap;
import java.util.Map;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import mark.tom.narcissus.template.IComponents;
import mark.tom.narcissus.template.IModuleFilter;

/**
 * @Description: 解析AndroidManifest文件读取自定义组件的工具类
 * @Author: Tom.Shen
 * @Package: mark.tom.narcissus
 * @Date: 2020/9/28
 * @Copyright: 版权归 Mark 所有
 */
class ManifestParser {

    private final Context mContext;
    private final Logger mLogger;
    private final IModuleFilter mFilter;

    ManifestParser(@NonNull Context context, @NonNull Logger mLogger, @Nullable IModuleFilter mFilter) {
        this.mContext = context;
        this.mLogger = mLogger;
        this.mFilter = mFilter;
    }

    Map<String, IComponents> parse() {
        Map<String, IComponents> modules = new HashMap<String, IComponents>();
        try {
            ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                    mContext.getPackageName(), PackageManager.GET_META_DATA);
            if (null == appInfo.metaData || appInfo.metaData.size() <= 0) {
                return modules;
            }
            for (String key : appInfo.metaData.keySet()) {
                if (null != mFilter && mFilter.filter(key)) {
                    continue;
                }
                IComponents result = null;
                try {
                    result = parseModule(String.valueOf(appInfo.metaData.get(key)));
                } catch (Exception ex) {
                    mLogger.e(ex.getMessage() + "");
                }
                if (null != result) {
                    modules.put(key, result);
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            mLogger.e("Unable to find metadata to parse Modules " + e.getMessage());
        }
        return modules;
    }

    private IComponents parseModule(String className) {
        Class<?> clazz;
        try {
            clazz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Unable to find Module : " + className, e);
        }
        Object module;
        try {
            module = clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Unable to instantiate Module implementation for " + clazz, e);
        }
        if (!(module instanceof IComponents)) {
            throw new RuntimeException("Expected instanceof Module, but found: " + module);
        }
        return (IComponents) module;
    }
}
